package com.ruoyi.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.system.constant.WxConstants;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.WeChatLoginResponse;
import com.ruoyi.system.domain.query.PostUserLikeQuery;
import com.ruoyi.system.domain.query.WeChatEventQuery;
import com.ruoyi.system.domain.query.WeChatLoginQuery;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.enums.EventAuditEnums;
import com.ruoyi.system.enums.EventProcessEnums;
import com.ruoyi.system.enums.EventTypeEnums;
import com.ruoyi.system.service.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class WeChatServiceImpl implements WeChatService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IIcUserService icUserService;

    @Autowired
    private IIcEventService icEventService;

    @Autowired
    private IIcEventInfoService icEventInfoService;

    @Autowired
    private IIcEventProcessService icEventProcessService;

    @Autowired
    private IIcPostsService icPostsService;

    @Autowired
    private IIcPostUserLikeService likeService;

    @Override
    public AjaxResult login(WeChatLoginQuery loginQuery) {
        // 基本参数校验
        if (StringUtils.isBlank(loginQuery.getCode())) {
            throw new RuntimeException("code 不能为空");
        }
        if (StringUtils.isBlank(loginQuery.getRawData())) {
            throw new RuntimeException("rawData 不能为空");
        }
        if (StringUtils.isBlank(loginQuery.getSignature())) {
            throw new RuntimeException("signature 不能为空");
        }
        JSONObject rawDataJson = JSON.parseObject(loginQuery.getRawData());
        HashMap<String, String> params = new HashMap<String, String>() {{
            put("js_code", loginQuery.getCode());
            put("appid", WxConstants.APP_ID);
            put("secret", WxConstants.APP_SECRET);
        }};
        // 进行登录
        String loginResponse = restTemplate.getForObject(WxConstants.LOGIN_URL, String.class, params);
        JSONObject loginResponseJson = JSON.parseObject(loginResponse);
        String sessionKey = String.valueOf(loginResponseJson.get("sessionKey"));
        // 校验signature
        String generateSignature = DigestUtils.sha1Hex(loginQuery.getRawData() + sessionKey);
        if (StringUtils.equals(loginQuery.getSignature(), generateSignature)) {
            return AjaxResult.error("签名验证失败");
        }
        String openId = String.valueOf(loginResponseJson.get("openid"));
        // 判断是否为新用户
        IcUser user = icUserService.selectIcUserByOpenId(openId);
        if (ObjectUtils.isEmpty(user)) {
            user = new IcUser();
            user.setIuOpenid(openId);
            user.setIuNickname(rawDataJson.getString("nickName"));
            user.setIuAvatarUrl(rawDataJson.getString("avatarUrl"));
            user.setCreateTime(new Date());
            int i = icUserService.insertIcUser(user);
            if (i <= 0) {
                throw new RuntimeException("添加用户失败");
            }
        }
        return AjaxResult.success(user);
    }

    @Override
    public AjaxResult getEventListByIuId(Long iuId) {
        List<IcEvent> events = icEventService.selectIcEventByIuId(iuId);
        if (CollectionUtils.isEmpty(events)) {
            return AjaxResult.success(Collections.emptyList());
        }
        List<IcEventVo> collect = events.stream().map(event -> {
            IcEventVo icEventVo = new IcEventVo();
            BeanUtils.copyProperties(event, icEventVo);
            String typeName = DictUtils.getDictLabel("ic_event_type", event.geteType());
            icEventVo.seteTypeName(typeName);
            String auditName = DictUtils.getDictLabel("ic_event_audit", String.valueOf(event.geteAudit()));
            icEventVo.seteAuditName(auditName);
            String processName = DictUtils.getDictLabel("ic_event_process", event.geteProcess());
            icEventVo.seteProcessName(processName);
            return icEventVo;
        }).collect(Collectors.toList());
        return AjaxResult.success(collect);
    }

    @Override
    public AjaxResult getEventDetailById(Long eventId) {
        IcEvent event = icEventService.selectIcEventByEId(eventId);
        IcEventVo icEventVo = new IcEventVo();
        BeanUtils.copyProperties(event, icEventVo);
        String typeName = DictUtils.getDictLabel("ic_event_type", event.geteType());
        icEventVo.seteTypeName(typeName);
        String auditName = DictUtils.getDictLabel("ic_event_audit", String.valueOf(event.geteAudit()));
        icEventVo.seteAuditName(auditName);
        String processName = DictUtils.getDictLabel("ic_event_process", event.geteProcess());
        icEventVo.seteProcessName(processName);
        // 获取事件信息
        IcEventInfo info = icEventInfoService.selectIcEventInfoByEId(eventId);
        IcEventInfoVo infoVo = new IcEventInfoVo();
        BeanUtils.copyProperties(info, infoVo);
        icEventVo.setInfo(infoVo);
        // 获取流程列表
        List<IcEventProcess> processes = icEventProcessService.selectIcEventProcessListByEId(eventId);
        List<IcEventProcessVo> processVos = Collections.emptyList();
        if (!CollectionUtils.isEmpty(processes)) {
            processVos = processes.stream().map(p -> {
                IcEventProcessVo processVo = new IcEventProcessVo();
                BeanUtils.copyProperties(p, processVo);
                String an = DictUtils.getDictLabel("ic_event_audit", String.valueOf(p.geteAudit()));
                processVo.setAuditName(an);
                String pn = DictUtils.getDictLabel("ic_event_process", String.valueOf(p.geteProcess()));
                processVo.setProcessName(pn);
                return processVo;
            }).collect(Collectors.toList());
        }
        icEventVo.setProcesses(processVos);
        return AjaxResult.success(icEventVo);
    }

    @Override
    public AjaxResult saveEventByQuery(WeChatEventQuery eventQuery) {
        IcEvent event = new IcEvent();
        BeanUtils.copyProperties(eventQuery, event);
        IcEventInfo info = new IcEventInfo();
        BeanUtils.copyProperties(eventQuery, info);
        event.seteAudit(0L);
        event.seteProcess("1");
        event.setCreateTime(new Date());
        icEventService.insertIcEvent(event);
        info.seteId(event.geteId());
        icEventInfoService.insertIcEventInfo(info);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult savePosts(IcPosts posts) {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        posts.setCreateTime(new Date());
        String ip = request.getRemoteHost();
        posts.setIpAddress(ip);
        int i = icPostsService.insertIcPosts(posts);
        if (i > 0) {
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }

    @Override
    public AjaxResult getPostsDetailById(Long postId) {
        IcPosts posts = icPostsService.selectIcPostsByPostId(postId);
        if (ObjectUtils.isEmpty(posts)) {
            return AjaxResult.success();
        }
        IcPostsVo icPostsVo = new IcPostsVo();
        BeanUtils.copyProperties(posts, icPostsVo);
        Long userId = posts.getUserId();
        IcUser user = icUserService.selectIcUserByIuId(userId);
        icPostsVo.setAuthorName(user.getIuNickname());
        icPostsVo.setViewCount(posts.getViewCount() + 1);
        // 更新浏览量
        posts.setViewCount(posts.getViewCount() + 1);
        icPostsService.updateIcPosts(posts);
        return AjaxResult.success(icPostsVo);
    }

    @Override
    public AjaxResult getPostUserLike(PostUserLikeQuery likeQuery) {
        IcPostUserLike postUserLike = new IcPostUserLike();
        postUserLike.setPostId(likeQuery.getPostId());
        postUserLike.setUserId(likeQuery.getUserId());
        List<IcPostUserLike> postUser = likeService.selectIcPostUserLikeList(postUserLike);
        if (CollectionUtils.isEmpty(postUser)) {
            return null;
        }
        IcPostUserLike pu = postUser.stream().findFirst().get();
        return AjaxResult.success(pu);
    }

    @Override
    public AjaxResult addPostUserLike(PostUserLikeQuery likeQuery) {
        IcPostUserLike postUserLike = new IcPostUserLike();
        IcPosts posts = icPostsService.selectIcPostsByPostId(likeQuery.getPostId());
        if (ObjectUtils.isEmpty(posts)) {
            throw new RuntimeException("post无法查询到");
        }
        IcUser user = icUserService.selectIcUserByIuId(likeQuery.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new RuntimeException("user无法查询到");
        }
        BeanUtils.copyProperties(likeQuery, postUserLike);
        int i = likeService.insertIcPostUserLike(postUserLike);
        // 点赞数+1
        posts.setLikeCount(posts.getLikeCount() + 1);
        icPostsService.updateIcPosts(posts);
        if (i > 0) {
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }
}
